using System;
using System.Linq;
using BSpec.Specification;
using BSpec.Specs;
using NUnit.Framework;

namespace concern_specs
{
    namespace with_scenario_of
    {
        public abstract class creating_a_concern_from_a_test_fixture_type : SpecificationBase<Concern>
        {
            protected override void setup_scenario()
            {
            }
        }

        public abstract class adding_scenarios_to_a_concern 
            : creating_a_concern_from_a_test_fixture_type
        {
        }
    }

    namespace given_a_type_that_contains_a_test_fixture
    {
        [TestFixture]
        public class when_creating_a_concern : with_scenario_of.creating_a_concern_from_a_test_fixture_type
        {
            protected override Concern create_subject()
            {
                return Concern.Create(this.GetType());
            }

            protected override void execute_scenario()
            {
                with_scenario_result(() => the_subject);
            }

            [Test]
            public void should_be_named_for_the_test_fixture_concern()
            {
                the_scenario_result<Concern>().Name.should_equal("Concern");
            }
        }
    }

    namespace given_a_type_that_does_not_contain_a_concern
    {
        [TestFixture]
        public class when_creating_a_concern : with_scenario_of.creating_a_concern_from_a_test_fixture_type
        {
            protected override Concern create_subject()
            {
                return Concern.Create(typeof(string));
            }

            protected override void execute_scenario()
            {
                with_scenario_result(() => the_subject);
            }

            [Test]
            public void should_return_a_null_concern()
            {
                the_scenario_result<Concern>().should_be_instance_of<NullConcern>();
            }
        }
    }

    namespace given_a_concern
    {
        [TestFixture]
        public class when_adding_a_scenario : with_scenario_of.adding_scenarios_to_a_concern
        {
            protected override Concern create_subject()
            {
                return Concern.Create(this.GetType());
            }

            protected override void execute_scenario()
            {
                the_subject.AddScenarioFor(this.GetType());
            }

            [Test]
            public void should_add_the_scenario_to_the_concern()
            {
                the_subject.Scenarios.should_not_be_empty();
            }

            [Test]
            public void should_add_a_context_to_the_scenario()
            {
                the_subject.Scenarios.First().Contexts.should_not_be_empty();
            }
        }
    }

    namespace given_a_concern_contains_a_scenario
    {
        [TestFixture]
        public class when_adding_a_scenario_that_already_exists : with_scenario_of.adding_scenarios_to_a_concern
        {
            protected override Concern create_subject()
            {
                return Concern.Create(this.GetType());
            }

            protected override void execute_scenario()
            {
                the_subject.AddScenarioFor(this.GetType());
                the_subject.AddScenarioFor(this.GetType());
            }

            [Test]
            public void should_not_add_duplicate_scenarios()
            {
                the_subject.Scenarios.Length.should_equal(1);
            }
        }
    }
}